//============================================================================
// Name        : WingEntityVisitor.java
// Author      : iron.yin@gmail.com
// Version     : v1.0
// Copyright   : RisingSun CO,.LTD
// Description : WingEntityVisitor.java in Java
//============================================================================
package cc.risingsun.wing.core;

import java.util.Set;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import cc.risingsun.wing.dai.entity.WingEntityBean;
import cc.risingsun.wing.ds.DataStruct;

/**
 *
 *@author iron.yin@gmail.com
 */
public class WingEntityClassVisitor extends ClassVisitor implements Opcodes{

	private static final String SUPER = Type.getInternalName(WingEntityBean.class);
	private static final Set<WingField> fields = DataStruct.hashSet();
	String owner;
	
	public WingEntityClassVisitor(){
		this(null);
	}

	public WingEntityClassVisitor(ClassVisitor cv) {
		super(ASM4,cv);
	}

	@Override
	public void visit(int version, int access, String name, String signature,
			String superName, String[] interfaces) {
		owner = name;
		super.visit(version, access, name, signature, SUPER, interfaces);
	}

	@Override
	public FieldVisitor visitField(int access, String name, String desc,
			String signature, Object value) {
		WingField i = new WingField(owner,name, Type.getType(desc));
		fields.add(i);
		return super.visitField(access, name, desc, signature, value);
	}

	@Override
	public MethodVisitor visitMethod(int access, String name, String desc,
			String signature, String[] exceptions) {
		MethodVisitor mv = super.visitMethod(access, name, desc, signature,
				exceptions);
		if (name.equals("<init>")) {
			mv.visitCode();
			mv.visitVarInsn(ALOAD, 0);
			mv.visitMethodInsn(INVOKESPECIAL, SUPER, "<init>", "()V");
			for (WingField field : fields) {
				mv.visitVarInsn(ALOAD, 0);
				mv.visitFieldInsn(GETFIELD, owner, "fieldsName",
						"Ljava/util/Set;");
				mv.visitLdcInsn(field.getName());
				mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "add",
						"(Ljava/lang/Object;)Z");
				mv.visitInsn(POP);
			}
			mv.visitInsn(RETURN);
		}
		return mv;
	}

	@Override
	public void visitEnd() {
		MethodVisitor mv = visitMethod(ACC_PUBLIC, "setValue",
				"(Ljava/lang/String;Ljava/lang/Object;)V", null,null);
		mv.visitCode();
		mv.visitVarInsn(ALOAD, 1);
		mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "toLowerCase",
				"()Ljava/lang/String;");
		mv.visitVarInsn(ASTORE, 3);
		for (WingField field : fields) {
			mv.visitVarInsn(ALOAD, 3);
			mv.visitLdcInsn(field.getName());
			mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals",
					"(Ljava/lang/Object;)Z");
			Label l2 = new Label();
			mv.visitJumpInsn(IFEQ, l2);
			mv.visitVarInsn(ALOAD, 0);
			mv.visitVarInsn(ALOAD, 2);
			field.invoke(mv);
			mv.visitInsn(RETURN);
			mv.visitLabel(l2);
		}
		mv.visitInsn(RETURN);
		mv.visitMaxs(0, 0);
		mv.visitEnd();
		fields.clear();
		super.visitEnd();
	}
	
	
}
